package com.onluy.frameworkcloud.batis.dbtobean;


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.onluy.frameworkcloud.data.annotation.Column;
import com.onluy.frameworkcloud.data.annotation.Table;
import com.onluy.frameworkcloud.data.entity.BaseEntity;
import com.onluy.frameworkcloud.data.entity.OperColumn;

public class CreateBeans {
    private static StringBuffer sb = null;
    private static boolean isDateType = false;
    private static boolean isBigDecimal = false;
    private static List<ColumnBeans> lists = null;
    private static CreateBeanConfig appConfig = null;

    public static void createJavaBean(String[][] tables, CreateBeanConfig appConfig) throws Exception {
        CreateBeans.appConfig = appConfig;
        Connection connection = null;

        try {
            connection = ConnectionTools.getConnection(appConfig.getDriverClassName(), appConfig.getDburl(),
                    appConfig.getDbusername(), appConfig.getDbpassword());

            for (int e = 0; e < tables.length; ++e) {
                run(connection, tables[e][0], tables[e][1], tables[e][2]);
            }
        } catch (Exception arg6) {
            arg6.printStackTrace();
            throw arg6;
        } finally {
            ConnectionTools.closeConnection((ResultSet) null, (PreparedStatement) null, connection);
        }

    }

    private static void run(Connection connection, String tableName, String packageName, String packagePath)
            throws Exception {
        sb = new StringBuffer();
        isDateType = false;
        isBigDecimal = false;
        lists = new ArrayList();
        createClassMessage(connection, tableName, packageName);
        sb.append("@Table(name=\"" + tableName.toUpperCase() + "\")\r");
        sb.append(
                "public class " + createClassName(tableName) + " extends " + BaseEntity.class.getSimpleName() + " {\r");
        sb.append("\tprivate static final long serialVersionUID = 1L;\r");
        queryFieldName(connection, tableName);
        createFildName();
        createMethod();
        createStaticFildName();
        if (appConfig.isOverrideToString()) {
            createToString();
        }

        if (appConfig.isGetField()) {
            createToFiled();
        }

        sb.append("}");
        String msg = sb.toString();
        if (isDateType) {
            msg = msg.replaceAll("#date#", "\rimport java.util.Date;\r");
        } else {
            msg = msg.replaceAll("#date#", "");
        }

        if (isBigDecimal) {
            msg = msg.replaceAll("#bigDecimal#", "\rimport java.math.BigDecimal;\r");
        } else {
            msg = msg.replaceAll("#bigDecimal#", "");
        }

        ExpJavaBean(msg, ".java", "", tableName, packagePath);
    }

    private static void ExpJavaBean(String msg, String fileType, String bs, String tableName, String packagePath) {
        File file = new File(packagePath);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdir();
        }

        FileOutputStream fos = null;
        BufferedWriter bw = null;

        try {
            String e = file + "\\" + bs + createClassName(tableName) + fileType;
            fos = new FileOutputStream(e);
            bw = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"));
            bw.write(msg);
            bw.flush();
            System.out.println("File creation success: " + e);
        } catch (FileNotFoundException arg27) {
            arg27.printStackTrace();

            try {
                bw.close();
                fos.close();
            } catch (IOException arg26) {
                arg26.printStackTrace();
            }

            try {
                bw.close();
                fos.close();
            } catch (IOException arg25) {
                arg25.printStackTrace();
            }
        } catch (IOException arg28) {
            arg28.printStackTrace();

            try {
                bw.close();
                fos.close();
            } catch (IOException arg24) {
                arg24.printStackTrace();
            }

            try {
                bw.close();
                fos.close();
            } catch (IOException arg23) {
                arg23.printStackTrace();
            }
        } finally {
            try {
                bw.close();
                fos.close();
            } catch (IOException arg22) {
                arg22.printStackTrace();
            }

        }

    }

    private static void createMethod() {
        Iterator i$ = lists.iterator();

        while (i$.hasNext()) {
            ColumnBeans list = (ColumnBeans) i$.next();
            sb.append("\tpublic " + list.getType() + " get" + toUpperCaseFirstOne(list.getName()) + "() {\r");
            sb.append("\t\treturn " + list.getName() + ";\r");
            sb.append("\t}\r\r");
            sb.append("\tpublic OperColumn set" + toUpperCaseFirstOne(list.getName()) + "(" + list.getType() + " "
                    + list.getName() + ") {\r");
            sb.append("\t\tthis." + list.getName() + " = " + list.getName() + ";\r");
            sb.append("\t\treturn addOperColumn(" + list.getCName() + ", \"" + list.getName() + "\", " + list.getName()
                    + ", " + list.getType() + ".class);\r");
            sb.append("\t}\r\r");
        }

    }

    private static void createStaticFildName() {
        sb.append("\t//Database field\r");
        Iterator i$ = lists.iterator();

        while (i$.hasNext()) {
            ColumnBeans list = (ColumnBeans) i$.next();
            sb.append("\tpublic static final String " + list.getCName() + " = \"" + list.getCName() + "\";\r");
        }

        sb.append("\t\r");
    }

    private static void createFildName() {
        sb.append("\r");
        Iterator i$ = lists.iterator();

        while (i$.hasNext()) {
            ColumnBeans list = (ColumnBeans) i$.next();
            sb.append("\t ");
            sb.append("\t\r");
            sb.append("\t@Column(name = " + list.getCName() + ")\r");
            sb.append("\tprivate " + list.getType() + " " + list.getName() + ";\r\r");
        }

    }

    public static String getSchema(Connection connection) throws Exception {
        String connUrl = connection.getMetaData().getURL().toLowerCase();
        if (connUrl.startsWith("jdbc:oracle")) {
            String schema = connection.getMetaData().getUserName();
            if (schema != null && schema.length() != 0) {
                return schema.toUpperCase().toString();
            } else {
                throw new Exception("Oracle database schema is not allowed to empty.");
            }
        } else {
            return "%";
        }
    }

    private static String queryTableComments(Connection connection, String tableName) {
        ResultSet rs = null;

        String e;
        try {
            rs = connection.getMetaData().getTables((String) null, getSchema(connection), tableName.toUpperCase(),
                    new String[]{"TABLE"});

            do {
                if (!rs.next()) {
                    e = null;
                    return e;
                }
            } while (rs.getString("REMARKS") == null);

            e = rs.getString("REMARKS");
        } catch (Exception arg12) {
            throw new RuntimeException(arg12.getMessage());
        } finally {
            try {
                ConnectionTools.closeConnection(rs, (PreparedStatement) null, (Connection) null);
            } catch (SQLException arg11) {
                arg11.printStackTrace();
            }

        }

        return e;
    }

    private static void queryFieldName(Connection connection, String tableName) throws Exception {
        tableName = tableName.toUpperCase();
        String sql = "select * from " + tableName + " where 1 = 0";
        PreparedStatement pre = null;

        try {
            Map e = getComments(connection, tableName);
            pre = connection.prepareStatement(sql);
            ResultSetMetaData metaData = pre.executeQuery().getMetaData();

            for (int i = 1; i <= metaData.getColumnCount(); ++i) {
                ColumnBeans columnBeans = new ColumnBeans();
                columnBeans.setClassName(createClassName(tableName));
                columnBeans.setName(formatTableColumnToClassFiled(metaData.getColumnName(i).toUpperCase()));
                columnBeans.setType(formatTableTypeToJavaType(metaData.getColumnType(i), metaData.getScale(i),
                        metaData.getColumnType(i) == 2 ? metaData.getPrecision(i) : metaData.getColumnDisplaySize(i)));
                columnBeans.setCName(metaData.getColumnName(i).toUpperCase());
                columnBeans.setCType(metaData.getColumnType(i));
                columnBeans.setLeng(metaData.getColumnDisplaySize(i));
                columnBeans.setComments((String) e.get(columnBeans.getCName()));
                lists.add(columnBeans);
            }
        } catch (Exception arg14) {
            throw arg14;
        } finally {
            try {
                ConnectionTools.closeConnection((ResultSet) null, pre, (Connection) null);
            } catch (SQLException arg13) {
                throw arg13;
            }
        }

    }

    private static Map<String, String> getComments(Connection connection, String tableName) throws Exception {
        tableName = tableName.toUpperCase();
        ResultSet rs = null;
        HashMap columnsMap = new HashMap();

        try {
            rs = connection.getMetaData().getColumns((String) null, getSchema(connection), tableName, "%");

            while (rs.next()) {
                columnsMap.put(rs.getString("COLUMN_NAME"), rs.getString("REMARKS"));
            }
        } catch (Exception arg11) {
            throw arg11;
        } finally {
            try {
                ConnectionTools.closeConnection(rs, (PreparedStatement) null, (Connection) null);
            } catch (SQLException arg10) {
                throw arg10;
            }
        }

        return columnsMap;
    }

    private static void createClassMessage(Connection connection, String tableName, String packageName) {
        String tableDesc = queryTableComments(connection, tableName);
        if (tableDesc == null) {
            tableDesc = "";
        }

        if (packageName != null) {
            sb.append("package " + packageName + ";\r");
        }

        sb.append("import " + BaseEntity.class.getName() + ";\r");
        sb.append("import " + OperColumn.class.getName() + ";\r");
        sb.append("import " + Table.class.getName() + ";\r");
        sb.append("import " + Column.class.getName() + ";\r");
        sb.append("\r");
        sb.append("#date# ");
        sb.append("#bigDecimal# ");
        sb.append("\r");
        sb.append("\t\r");
    }

    private static String getNewTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date());
    }

    private static String createClassName(String str) {
        StringBuffer sc = new StringBuffer();
        if (str == null) {
            throw new RuntimeException("表名称为空！");
        } else {
            String[] className = str.toLowerCase().split("_");
            String[] arr$ = className;
            int len$ = className.length;

            for (int i$ = 0; i$ < len$; ++i$) {
                String code = arr$[i$];
                sc.append(code.substring(0, 1).toUpperCase() + code.substring(1, code.length()));
            }

            return sc.toString();
        }
    }

    private static String formatTableTypeToJavaType(int columnType, int scale, int length) throws SQLException {
        String javaType = "String";
        switch (columnType) {
            case -15 :
            case -9 :
            case -1 :
            case 1 :
            case 12 :
            case 2005 :
            case 2011 :
                javaType = "String";
                break;
            case -7 :
            case 16 :
                javaType = "Boolean";
                break;
            case -6 :
                javaType = "Byte";
                break;
            case -5 :
                javaType = "Long";
                break;
            case -4 :
            case -3 :
            case -2 :
            case 2004 :
                javaType = "byte[]";
                break;
            case 0 :
            case 70 :
            case 1111 :
            case 2000 :
            case 2001 :
            case 2002 :
            case 2003 :
            case 2006 :
                javaType = "Object";
                break;
            case 2 :
            case 3 :
                if (scale <= 0 && length <= 18 && !appConfig.isForceBigDecimals()) {
                    if (length > 9) {
                        javaType = "Long";
                    } else {
                        javaType = "Integer";
                    }
                } else {
                    javaType = "BigDecimal";
                    isBigDecimal = true;
                }
                break;
            case 4 :
                javaType = "Integer";
                break;
            case 5 :
                javaType = "Short";
                break;
            case 6 :
            case 8 :
                javaType = "Double";
                break;
            case 7 :
                javaType = "Float";
                break;
            case 91 :
            case 92 :
            case 93 :
                javaType = "Date";
                isDateType = true;
        }

        return javaType;
    }

    private static String formatTableColumnToClassFiled(String code) {
        try {
            code = code.toLowerCase();
            String[] e = code.split("_");
            String msg = e[0];

            for (int i = 1; i < e.length; ++i) {
                msg = msg + e[i].substring(0, 1).toUpperCase() + e[i].substring(1, e[i].length());
            }

            return msg;
        } catch (Exception arg3) {
            throw new RuntimeException(
                    "Create the JavaBeans property name failed, possibly due to the incoming table name error.\r"
                            + arg3.getMessage());
        }
    }

    private static void createToString() {
        sb.append("\t//override toString Method \r");
        sb.append("\tpublic String toString() {\r");
        sb.append("\t\tStringBuffer sb = new StringBuffer();\r");
        sb.append("\t\tsb.append(\"{\");\r");
        Iterator i$ = lists.iterator();

        while (i$.hasNext()) {
            ColumnBeans bean = (ColumnBeans) i$.next();
            sb.append("\t\tsb.append(\"" + bean.getName() + "=\"+this.get" + toUpperCaseFirstOne(bean.getName())
                    + "()+\", \");\r");
        }

        sb.append("\t\tsb.append(\"}\");\r");
        sb.append("\t\treturn sb.toString();\r");
        sb.append("\t}\r");
    }

    private static void createToFiled() {
        StringBuffer sbb = new StringBuffer();
        Iterator requ = lists.iterator();

        while (requ.hasNext()) {
            ColumnBeans bean = (ColumnBeans) requ.next();
            sbb.append("\"").append(bean.getName()).append("\",");
        }

        String requ1 = sbb.toString().substring(0, sbb.toString().length() - 1);
        sb.append("\t//return String[] filed; \r");
        sb.append("\tpublic String[] getField() {\r");
        sb.append("\t\treturn new String[]{" + requ1 + "};\r");
        sb.append("\t}\r");
    }

    private static String toUpperCaseFirstOne(String s) {
        return Character.isUpperCase(s.charAt(0)) ? s : Character.toUpperCase(s.charAt(0)) + s.substring(1);
    }
}